package com.niiwoo.civet.account.service.local;/**
 * Created by DELL on 2017/12/15.
 */

import com.alibaba.fastjson.JSON;
import com.niiwoo.civet.account.dao.entity.AccountFundTransferOrder;
import com.niiwoo.civet.account.dao.entity.AccountFundTransferOrderExample;
import com.niiwoo.civet.account.dao.mapper.AccountFundTransferOrderMapperExt;
import com.niiwoo.civet.account.dto.bill.AddBillAndChangeBalanceDTO;
import com.niiwoo.civet.account.dto.bill.AddBillDetailDTO;
import com.niiwoo.civet.account.dto.response.SubmitAccountFundTransferReponseDTO;
import com.niiwoo.civet.account.enums.*;
import com.niiwoo.civet.account.service.local.bill.BillFacade;
import com.niiwoo.civet.base.enums.ChannelCodeEnum;
import com.niiwoo.civet.trade.constant.PlatformConstant;
import com.niiwoo.tripod.lanmao.component.LanMaoSequence;
import com.niiwoo.tripod.provider.exception.BizException;
import com.niiwoo.tripod.service.component.SnowflakeIdWorker;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 账户资金划拨Serivce
 *
 * @author xiaoyingping
 * @create 2017-12-15 15:01
 **/
@Service
@Slf4j
public class AccountFundTransferService {

    @Autowired
    private AccountFundTransferOrderMapperExt accountFundTransferOrderMapper;

    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;
    @Autowired
    private LanMaoSequence lanMaoSequence;
    @Autowired
    private AccountService accountService;
    @Autowired
    private BillFacade billFacade;



    /**
     * 新增资金划拨订单
     * @param accountFundTransferOrder
     */
    @Transactional
    public void insertAccountFundTransferOrder(AccountFundTransferOrder accountFundTransferOrder){
        accountFundTransferOrder.setId(snowflakeIdWorker.nextId());
        accountFundTransferOrder.setRequestNo(lanMaoSequence.getRequestNo());
        accountFundTransferOrder.setStatus(AccountFundTransferStatusEnum.HANDLING.getValue());
        Date curDate = new Date();
        accountFundTransferOrder.setCreateTime(curDate);
        accountFundTransferOrder.setUpdateManager(0L);
        accountFundTransferOrder.setUpdateTime(curDate);

        accountFundTransferOrderMapper.insertSelective(accountFundTransferOrder);
    }


    /**
     * 处理回调请求
     * @param accountFundTransferOrderId
     * @param isTansferSuccess
     * @return
     */
    @Transactional
    public SubmitAccountFundTransferReponseDTO processSubmitFundTransferNotify(Long accountFundTransferOrderId, Boolean isTansferSuccess) {
        AccountFundTransferOrder accountFundTransferOrder = accountFundTransferOrderMapper.selectByPrimaryKeyForUpdate(accountFundTransferOrderId);
        log.info("账户资金划拨,accountFundTransferOrder：{}", JSON.toJSONString(accountFundTransferOrder));
        if(AccountFundTransferStatusEnum.HANDLING.getValue() == accountFundTransferOrder.getStatus()){
            if (isTansferSuccess) {
                log.info("账户资金划拨成功：accountFundTransferOrder:{}", JSON.toJSONString(accountFundTransferOrder));
                //修改资金划拨订单的状态
                updateAccountFundTransferStatus(accountFundTransferOrder.getId(), AccountFundTransferStatusEnum.SUCCESS);
                //变更余额 + 记账
                saveAccountBillList(accountFundTransferOrder);
            } else {
                log.error("账户资金划拨失败：accountFundTransferOrder:{}", JSON.toJSONString(accountFundTransferOrder));
                //修改资金划拨订单的状态
                updateAccountFundTransferStatus(accountFundTransferOrder.getId(), AccountFundTransferStatusEnum.FAIL);
            }
        }else{
            log.warn("账户资金划拨，当前状态已非处理中：accountFundTransferOrder:{}", JSON.toJSONString(accountFundTransferOrder));
        }

        //返回
        SubmitAccountFundTransferReponseDTO result = new SubmitAccountFundTransferReponseDTO();
        result.setTransferSuccess(isTansferSuccess);
        result.setPayAccountBalance(accountService.loadAccountById(accountFundTransferOrder.getPayAccountId()).getAvailableAmount());
        result.setReceiveAccountBalance(accountService.loadAccountById(accountFundTransferOrder.getReceiveAccountId()).getAvailableAmount());
        return result;
    }

    /**
     * 查询资金划拨订单：不存在则抛出异常
     *
     * @param requestNo
     * @return
     */
    public AccountFundTransferOrder loadByRequestNo(String requestNo) {
        AccountFundTransferOrderExample example = new AccountFundTransferOrderExample();
        AccountFundTransferOrderExample.Criteria criteria = example.createCriteria();
        criteria.andRequestNoEqualTo(requestNo);

        List<AccountFundTransferOrder> list = accountFundTransferOrderMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(list)) {
            throw new BizException("ACC10035");
        }
        return list.get(0);
    }




    /**
     * 修改资金划拨订单的状态
     *
     * @param id
     * @param newStatus
     */
    private void updateAccountFundTransferStatus(Long id, AccountFundTransferStatusEnum newStatus) {
        Assert.notNull(id, "id不能为空");

        AccountFundTransferOrder record = new AccountFundTransferOrder();
        record.setId(id);
        record.setStatus(newStatus.getValue());
        record.setUpdateTime(new Date());
        accountFundTransferOrderMapper.updateByPrimaryKeySelective(record);
    }


    private void saveAccountBillList(AccountFundTransferOrder accountFundTransferOrder) {
        BillSecondSubjectEnum billSecondSubjectEnumIn = BillSecondSubjectEnum.USER_TRANSFER_IN;
        BillSecondSubjectEnum billSecondSubjectEnumOut = BillSecondSubjectEnum.USER_TRANSFER_OUT;
        if(PlatformConstant.PLATFORM_USER_ID.equals(accountFundTransferOrder.getUserId())){
            billSecondSubjectEnumIn = BillSecondSubjectEnum.PLATFORM_TRANSFER;
            billSecondSubjectEnumOut = BillSecondSubjectEnum.PLATFORM_TRANSFER_OUT;
        }

        /**===转出账户===*/
        AddBillDetailDTO billDetailDTO = new AddBillDetailDTO();
        billDetailDTO.setAmount(accountFundTransferOrder.getAmount());
        billDetailDTO.setBillSecondSubjectEnum(billSecondSubjectEnumOut);

        AddBillAndChangeBalanceDTO billDTO = new AddBillAndChangeBalanceDTO();
        billDTO.setAccountId(accountFundTransferOrder.getPayAccountId());
        billDTO.setAmount(accountFundTransferOrder.getAmount());
        billDTO.setInoutType(InoutTypeEnum.OUT_TYPE);
        billDTO.setOrderId(accountFundTransferOrder.getId());
        billDTO.setOrderType(OrderTypeEnum.FUND_TRANSFER);
        billDTO.setRequestNo(accountFundTransferOrder.getRequestNo());
        billDTO.setStatus(BillStatusEnum.SUCCESS);
        billDTO.setChannelCode(ChannelCodeEnum.APP);
        billDTO.setAddBillDetailDTOList(Arrays.asList(billDetailDTO));
        billDTO.setRelationAccountId(accountFundTransferOrder.getReceiveAccountId());
        billDTO.setRelationUserId(accountFundTransferOrder.getUserId());
        billFacade.addBillAndChangeBalance(billDTO);

        /**===转入账户===*/
        billDetailDTO = new AddBillDetailDTO();
        billDetailDTO.setAmount(accountFundTransferOrder.getAmount());
        billDetailDTO.setBillSecondSubjectEnum(billSecondSubjectEnumIn);

        billDTO = new AddBillAndChangeBalanceDTO();
        billDTO.setAccountId(accountFundTransferOrder.getReceiveAccountId());
        billDTO.setAmount(accountFundTransferOrder.getAmount());
        billDTO.setInoutType(InoutTypeEnum.IN_TYPE);
        billDTO.setOrderId(accountFundTransferOrder.getId());
        billDTO.setOrderType(OrderTypeEnum.FUND_TRANSFER);
        billDTO.setRequestNo(accountFundTransferOrder.getRequestNo());
        billDTO.setStatus(BillStatusEnum.SUCCESS);
        billDTO.setChannelCode(ChannelCodeEnum.APP);
        billDTO.setAddBillDetailDTOList(Arrays.asList(billDetailDTO));
        billDTO.setRelationAccountId(accountFundTransferOrder.getPayAccountId());
        billDTO.setRelationUserId(accountFundTransferOrder.getUserId());
        billFacade.addBillAndChangeBalance(billDTO);
    }

}
